package com.xiu.travel.config;

import com.xiu.travel.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Configuration
public class  SecurityConfig
{
    @Autowired
    private AuthenticationConfiguration authenticationConfiguration;
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    @Bean
    public PasswordEncoder passwordEncoder()
    {
        return new BCryptPasswordEncoder();
    }


    @Bean
    public AuthenticationManager authenticationManager() throws Exception
    {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception
    {
        //Swagger资源
        List<String> permitAllResource = new ArrayList<>(Arrays.asList("/data/**", "/oauth/**", "/login/**", "/logout/**", "/test/**", "/druid/**", "/swaggger-ui.html", "/doc.html", "/v3/**", "/swagger-resources", "/swagger-resources/**", "/webjars/**"));
        String[] resourcesArray=permitAllResource.toArray(new String[]{});

        http
                //关闭csrf
                .csrf(AbstractHttpConfigurer::disable)
                //不通过Session获取SecurityContext
                .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(authorize ->
                                       {
                                           try
                                           {
                                               authorize
                                                       // 放行登录接口
                                                       .requestMatchers("/admin/open/**","/portal/open/**")
                                                       .permitAll()
                                                       .requestMatchers(resourcesArray).permitAll()
                                                       // 其余的都需要权限校验
                                                        .anyRequest().authenticated()
                                                       // 防跨站请求伪造
                                                       .and()
                                                       .csrf(AbstractHttpConfigurer::disable);
                                           } catch (Exception e)
                                           {
                                               throw new RuntimeException(e);
                                           }
                                       }
                );

        // 对于登录接口 允许匿名访问

        // 除上面外的所有请求全部需要鉴权认证


        http.addFilterAt(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        http.exceptionHandling()
                //配置认证失败处理器
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);

        http.cors();

        return http.build();
    }
}
